import React, { useState, ChangeEvent, ReactElement, useEffect, KeyboardEvent, useRef } from "react";
import classNames from "classnames";
import { library } from "@fortawesome/fontawesome-svg-core";
import { fas } from "@fortawesome/free-solid-svg-icons";
import Input, { IInputProps } from "../Input/input.tsx";
import Icon from "../Icon/icon.tsx";
import useDebounce from "../../hooks/useDebounce.tsx";
import useClickOutside from "../../hooks/useClickOutside.tsx";
library.add(fas); // 添加全部图标

interface DataSourceObject {
    value: string;
    number: number;
}
export type DataSourceType<T = {}> = T & DataSourceObject;

export interface IAutoCompleteProps extends Omit<IInputProps, "onSelect"> {
    fetchSuggestions: (str: string) => DataSourceType[] | Promise<DataSourceType[]>;
    onSelect?: (item: DataSourceType) => void;
    renderOption?: (item: DataSourceType) => ReactElement;
}
const AutoComplete: React.FC<IAutoCompleteProps> = (props) => {
    const { fetchSuggestions, onSelect, value, renderOption, ...restProps } = props;
    const [inputValue, setInputValue] = useState<string>(value as string);
    const [suggestions, setSuggestions] = useState<DataSourceType[]>([]); // 下拉框
    const [loading, setLoading] = useState<boolean>(false); // 用于异步请求loading展示
    const debouncedValue = useDebounce(inputValue, 800); // 创建防抖值
    const [highlightIndex, setHighlightIndex] = useState<number>(-1); // 指示当前高亮项
    const triggerSearch = useRef(false); // useRef变化不会引起组建的重新渲染,且在整个组件生命周期内保持不变
    const componentRef = useRef<HTMLDivElement>(null); // 指向整个组件的dom节点
    useClickOutside(componentRef, () => {
        setSuggestions([]); // 清空下拉
    });
    useEffect(() => {
        if (debouncedValue && triggerSearch.current) {
            const results = fetchSuggestions(debouncedValue); // 获取的联想数据
            if (results instanceof Promise) {
                setLoading(true);
                // 处理异步结果
                results.then(data => {
                    setLoading(false);
                    setSuggestions(data);
                });
            } else {
                setSuggestions(results);
            }
        } else {
            setSuggestions([]); // 置空
        }
        setHighlightIndex(-1); // 每次获取结果后重置高亮
    }, [debouncedValue]);
    // 处理高亮索引
    const highlight = (index: number) => {
        if (index < 0) index = 0;
        if (index >= suggestions.length) {
            index = suggestions.length - 1;
        }
        setHighlightIndex(index);
    };
    // 处理键盘事件
    const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
        switch (e.code) {
            case "Enter":
                if (suggestions[highlightIndex]) {
                    handleSelect(suggestions[highlightIndex]);
                }
                break;
            //向上
            case "ArrowUp":
                highlight(highlightIndex - 1);
                break;
            //向下
            case "ArrowDown":
                highlight(highlightIndex + 1);
                break;
            //取消
            case "Escape":
                setSuggestions([]);
                break;
            default:
                break;
        }
    }
    // 处理输入
    const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
        const value = e.target.value.trim();
        setInputValue(value); // 更新inputValue
        triggerSearch.current = true;
    }
    // 处理下拉内容
    const handleSelect = (item: DataSourceType) => {
        // input内填充选择的值 && 以及关闭下拉框 && 并且触发自定义的onSelect回调
        setInputValue(item.value);
        setSuggestions([]);
        if (onSelect) {
            onSelect(item);
        }
        triggerSearch.current = false;
    }
    // 处理渲染方式
    const renderTemplate = (item: DataSourceType) => {
        return renderOption ? renderOption(item) : item.value;
    }
    // 生成下拉内容
    const generateDropdown = () => {
        return (
            <ul>
                {suggestions.map((item, index) => {
                    const classes = classNames("suggestion-item", {
                        "item-highlighted": index === highlightIndex,
                    });
                    return (
                        <li key={index} className={classes} onClick={() => handleSelect(item)} style={{ listStyle: "none" }}>
                            {renderTemplate(item)}
                        </li>
                    );
                })}
            </ul>
        );
    }
    return (
        <div className="auto-complete" ref={componentRef}>
            <Input value={inputValue} onChange={handleChange} onKeyDown={handleKeyDown}  {...restProps} />
            {loading && <Icon icon="spinner" theme="danger" spin />}
            {suggestions.length > 0 && generateDropdown()}
        </div>
    );
}
export default AutoComplete;